package com.example.gitstudy.other;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.val;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author hwj
 * @date 2022/12/29 14:13
 * @描述；java实体类和map对象的相互转换
 */
public class TestCopy {


    /**
     *
     * 实体类对象转Map对象
     * 1.使用Fastjson
     *
     *
     * <dependency>
     *     <groupId>com.alibaba</groupId>
     *     <artifactId>fastjson</artifactId>
     *     <!--（起码1.2.48以上）因为这个版本以下存在漏洞-->
     *     <version>版本根据自己需要</version>
     *<dependency>
     * @param obj
     * @param <T>
     * @return
     */
    public <T> Map<String, Object> toMapByJson(T obj) {
        // 默认序列化为数字类型的时间戳
        // String jsonStr = JSON.toJSONString(obj);

        // Fastjson内置了一个默认的日期格式yyyy-MM-dd HH:mm:ss，
        // 可以通过在调用JSON.toJSONString时传入SerializerFeature.WriteDateUseDateFormat来启用。
        // 通过修改默认的时间格式，结合启用默认日期格式，也可以达到按指定日期格式序列化的目的
        // JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
        String jsonStr = JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
        Map<String, Object> map = JSON.parseObject(jsonStr, new TypeReference<Map<String, Object>>() {
        });
        return map;
    }


    /**
     * 实体类对象转Map对象
     * 2.使用反射
     * @param obj
     * @param <T>
     * @return
     */
    public <T> Map<String, Object> toMapByReflect(T obj) {
        Field[] fields = obj.getClass().getDeclaredFields();
        Map<String, Object> map = new HashMap<>();

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (Field f : fields) {
                f.setAccessible(true);
                Object val = f.get(obj);
                if (f.getType() == Date.class) {
                    map.put(f.getName(), val!=null?sdf.format(val):"");//避免val为空，时间转换报错
                } else {
                    map.put(f.getName(), val);
                }
            }
        } catch (IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }

        return map;
    }

    /**
     *  Map对象转实体类对象
     *  1.使用Fastjson
     * @param map
     * @param type
     * @param <T>
     * @return
     */
    public <T> T toObjByJson(Map<String, Object> map, Class<T> type) {
        // 日期格式参照上文
        T t = JSON.parseObject(JSON.toJSONString(map), type);
        return t;
    }

    /**
     *  Map对象转实体类对象
     *  2.使用反射
     * @param map
     * @param type
     * @param <T>
     * @return
     */
    public <T> T toObjByReflect(Map<String, Object> map, Class<T> type) {
        T obj = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            obj = type.newInstance();
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field f : fields) {
                int mod = f.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                f.setAccessible(true);
                if (map.containsKey(f.getName())) {
                    if (f.getType() == Date.class) {
                        f.set(obj, sdf.parse((String) map.get(f.getName())));
                    } else {
                        f.set(obj, map.get(f.getName()));
                    }
                }
            }

        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | ParseException e) {
            e.printStackTrace();
        }

        return obj;
    }



    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        Person p = new Person(1, "jack", new Date());
        System.out.println("原始实体对象:"+p);
        TestCopy testCopy = new TestCopy();
        /**
         * 实体转map(反射)
         */
        Map<String, Object> map = testCopy.toMapByReflect(p);
        System.out.println("实体转map(反射):"+map);
        /**
         * 体转map(fastJson)
         */
        Map<String, Object> map1 = testCopy.toMapByJson(p);
        System.out.println("体转map(fastJson):"+map1);

        /**
         * map转实体(fastJson)
         */
        Person person = testCopy.toObjByJson(map, Person.class);
        System.out.println(person);

        /**
         * map转实体(反射)
         */
        Person person1 = testCopy.toObjByReflect(map, Person.class);
        System.out.println(person1);



    }
}
